package com.midian.common.dao;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.midian.common.dao.SearchHelper.LinkType;
import com.midian.common.dao.SearchHelper.Type;
import com.midian.common.exception.ModelException;
import com.midian.common.pager.Pager;
import com.midian.common.system.SysStatic;
import com.midian.common.utils.DateHelper;
import com.midian.model.common.BaseModel;
import com.midian.model.common.Model;

/**
 * 
 * @Title:工具类
 * @Desription:所有dao的父类
 * @Company:MDKG
 * @ClassName:BaseDaoTemplet.java
 * @Author:zhucong
 * @CreateDate:2013-6-7 下午5:25:50  
 * @UpdateUser:zhucong  
 * @Version:0.1
 */
public class BaseDaoTemplet<T extends Model> extends HibernateDaoSupport{
	/**Log4j日志对象*/
	Logger log=Logger.getLogger(BaseDaoTemplet.class);
	/**实体类对象*/
	private Class<T> entityClass;
	public BaseDaoTemplet(){
		
	}
	public Class<T> getEntityClass() {
		return entityClass;
	}

	public void setEntityClass(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 添加对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:26:50
	 * @param object 目标对象
	 * @throws ModelException
	 */
	public void add(T object) throws ModelException {
		try {
			super.getHibernateTemplate().save(object);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("添加" +object.toString()+ "出错!", e);
		}
	}
	
	/**
	 * 添加同时flush session
	 * @param object
	 * @throws ModelException
	 */
	public void addAndFlush(T object) throws ModelException {
		Session session = null;
		try {
			session = super.getSession();
			session.save(object);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("添加" +object.toString()+ "出错!", e);
		} finally {
			session.clear();
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 保存或修改指定的对象，当指定对象的标识为null时，保存对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:27:08
	 * @param object 目标对象
	 * @throws ModelException
	 */
	public void saveOrUpdate(T object) throws ModelException {
		try {
			super.getHibernateTemplate().saveOrUpdate(object);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("更新" + object.toString() + " 出错！", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 修改对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:27:23
	 * @param object 目标对象
	 * @throws ModelException
	 */
	public void update(T object) throws ModelException {
		try {
			super.getHibernateTemplate().update(object);
		} catch (Exception e) {
			throw new ModelException("修改" + object.toString() + " 出错", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 合并对象。如在一个session中有2个标识相同的对象，把2个对象的属性合并后保存
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:27:36
	 * @param object 目标对象
	 * @throws ModelException
	 */
	public void merge(T object) throws ModelException {
		try {
			super.getHibernateTemplate().merge(object);
		} catch (Exception e) {
			throw new ModelException("修改" + object.toString() + " 出错", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 修改指定对象的指定属性值
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:27:54
	 * @param obj 需要修改的对象
	 * @param propertyName 需要修改的属性名称
	 * @param propertyValue 指定修改为的新值
	 * @param sh 指定的修改条件
	 * @throws ModelException
	 */
	public void update(T obj,String propertyName,Object propertyValue,SearchHelper sh)throws ModelException{
		List<Object> valueList = new ArrayList<Object>();
		StringBuilder sb = new StringBuilder("update ").append(obj.getClass().getName()).append(" o set o.");
		sb.append(propertyName).append(" = ?").append(" where ");
		valueList.add(propertyValue);
		Type type = sh.getType();
		String property = sh.getAttrValueName();//获取属性
		Object value = getPropertyValue(obj, property);
		sb.append(sh.getAttr());
		if(Type.EQ == type){
			sb.append(" = ?");
			valueList.add(value);
		}
		//System.out.println(sb.toString());
		this.update(sb.toString(), valueList.toArray());	
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 修改指定对象的指定属性值,条件为对象标识
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:28:12
	 * @param obj 需要修改的对象
	 * @param propertyName 需要修改的属性名称
	 * @param propertyValue 指定修改为的新值
	 * @throws ModelException
	 */
	public void update(BaseModel obj,String propertyName,Object propertyValue)throws ModelException{
		List<Object> valueList = new ArrayList<Object>();
		StringBuilder sb = new StringBuilder("update ").append(obj.getClass().getName()).append(" o set o.");
		sb.append(propertyName).append(" = ?").append(" where ");
		valueList.add(propertyValue);	
		sb.append("o.id = ?");
		valueList.add(obj.getId());
		//System.out.println(sb.toString());
		this.update(sb.toString(), valueList.toArray());	
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 按条件逻辑删除对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:28:28
	 * @param obj 需要删除的对象
	 * @param sh 删除条件
	 * @throws ModelException
	 */
	public void deleteLogic(T obj,SearchHelper sh)throws ModelException{
		this.update(obj,"delFlag",SysStatic.DELFLAG,sh);
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 根据标识逻辑删除对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:29:38
	 * @param id 主键
	 * @throws ModelException
	 */
	public void deleteLogic(Serializable id)throws ModelException{
		String hql = "update "+entityClass.getName()+" o set o.delFlag = "+SysStatic.DELFLAG +" where o.id=?";
		if(id==null||StringUtils.isBlank(id.toString())){
			return;
		}
		try{
			update(hql, new Object[]{id});
		}catch (Exception e) {
			throw new ModelException("删除对象失败!",e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 批量逻辑删除对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:29:55
	 * @param ids 主键集合
	 * @throws ModelException
	 */
	public void deleteLogic(Serializable[] ids)throws ModelException{
		if(ids==null||ids.length==0){
			throw new ModelException("请选择您要删除的记录！");
		}
		for (Serializable id : ids) {
			deleteLogic(id);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 根据id获取对象信息
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:30:13
	 * @param id 主键
	 * @return
	 * @throws ModelException
	 */
	public T get(Serializable id) throws ModelException {
		try {
			if(id==null||StringUtils.isBlank(id.toString())){
				throw new ModelException("请选择你要获取详细信息的记录!");
			}
			T t = (T)super.getHibernateTemplate().get(entityClass, id);
			if(t==null){
				throw new ModelException("您查询的记录已经不存在！");
			}
			return t;
		} catch (Exception e) {
			if(e instanceof ModelException){
				throw (ModelException)e;
			}else{
				throw new ModelException("--------------- get" + entityClass.getName() + " by id=" + id + " false", e);
			}
		}
	}

	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 根据id物理删除对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:30:24
	 * @param id 主键
	 * @throws ModelException
	 */
	public void delete(Serializable id) throws ModelException {
		try {
			Object obj = get(id);
			if(obj!=null){
				super.getHibernateTemplate().delete(obj);
			}
		} catch (Exception e) {
			throw new ModelException("--------------- delete " + entityClass.getName() + " by id=" + id + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 批量删除记录。物理删除
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:30:37
	 * @param ids 主键集合
	 * @throws ModelException
	 */
	public void delete(Serializable[] ids)throws ModelException{
		if(ids==null||ids.length==0){
			throw new ModelException("请选择您要删除的记录！");
		}
		for (Serializable id : ids) {
			delete(id);
		}
	}

	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 快速删除对象，采取直接的delete 语句执行 物理删除
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:30:53
	 * @param obj 条件值
	 * @param propertyName 删除条件
	 * @throws ModelException
	 */
	public void delete(Serializable obj,String propertyName)throws ModelException{
		String hql = "delete "+entityClass.getName()+" where "+propertyName+" =?";
		try {
			this.update(hql, new Object[] { obj });
		} catch (Exception e) {
			throw new ModelException("--------------- delete " + entityClass.getName() + " by propertyName=" + propertyName + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 批量查询
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:31:17
	 * @param hql HQL语句
	 * @return
	 * @throws ModelException
	 */
	@SuppressWarnings("rawtypes")
	public List find(String hql) throws ModelException {
		try {
			return super.getHibernateTemplate().find(hql);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 单个查询
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:31:32
	 * @param hql HQL语句
	 * @param values 参数集合
	 * @return
	 * @throws ModelException
	 */
	public Object findObject(String hql,Object[] values)throws ModelException{
		try {
			Session session = super.getSession();
			Query query = session.createQuery(hql);
			int i=0;
			if(values!=null){
				for (Object object : values) {
					query.setParameter(i, object);
					i++;
				}
			}
			return query.uniqueResult();
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- 查询单个对象失败",e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 分页查询
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:31:57
	 * @param queryString HQL语句
	 * @param pager 分页对象
	 * @return
	 * @throws ModelException
	 */
	@SuppressWarnings("rawtypes")
	public List pageFind(final String queryString, final Pager pager) throws ModelException {
		return pageFind(queryString, null, pager);
	}

	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 分页查询
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:33:16
	 * @param queryString HQL语句
	 * @param values 参数集合
	 * @param pager 分页对象
	 * @return
	 * @throws ModelException
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List pageFind(final String queryString, final Object[] values, final Pager pager) throws ModelException {
		try {
			return (List) super.getHibernateTemplate().execute(new HibernateCallback<List>() {
				public List<T> doInHibernate(Session session) throws HibernateException {
					Query queryObject = session.createQuery(queryString);
					if(pager!=null){
						try {
							pager.setTotalRows(getCount(queryString,values));
						} catch (ModelException e) {
							//e.printStackTrace();
							throw new HibernateException("--查询记录总数失败--",e);
						}
						queryObject.setFirstResult(pager.getStartRow());
						queryObject.setMaxResults(pager.getPageSize());
					}
					setParamList(queryObject,values);
					List list = queryObject.list();
					if(!list.isEmpty()){
						//设置分页组件对象
						Object obj = list.get(0);
						if(obj instanceof Object[]) {
							Object[] objArrs = (Object[])obj;
							for(Object searchObj : objArrs) {
								if(searchObj instanceof Model) {
									setObjPager(searchObj, pager);
									break;
								}
							}
						} else if(obj instanceof Model) {
							setObjPager(obj, pager);
						}
					}
					return list;
				}
			});
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- 分页查询" + queryString + " 出错",e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 设置分页对象
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:33:55
	 * @param obj 目标对象
	 * @param pager 分页对象
	 */
	private void setObjPager(Object obj, Pager pager) {
		if(obj instanceof Model){
			try {
				//System.out.println("className:"+obj.getClass());
				Method method = obj.getClass().getMethod("setPager", Pager.class);
				method.invoke(obj, pager);
			} catch (Exception e) {
				//e.printStackTrace();
			}
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 参数设置
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:34:32
	 * @param query query对象
	 * @param values 参数集合
	 */
	private void setParamList(Query query,Object[] values){
		if (values != null) {
			//参数下标
			int index = 0;
			for (int i = 0; i < values.length; i++) {
				Object obj = values[i];
				if(obj instanceof List){
					//如果参数类型为集合类型，进行循环赋值
					List params = (List)obj;
					for (Object param : params) {
						query.setParameter(index, param);
						index++;
					}
				}else{
					query.setParameter(index, obj);
					index++;
				}
			}
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 执行指定的查询语句
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:34:58
	 * @param hql HQL语句
	 * @param values 参数集合
	 * @return
	 * @throws ModelException
	 */
	public List find(String hql, Object[] values) throws ModelException {
		try {
			return pageFind(hql, values,null);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 执行指定的查询语句
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:36:06
	 * @param hql HQL语句
	 * @param currPage 当前页
	 * @param pageSize 每页行数
	 * @return
	 * @throws ModelException
	 */
	public List find(String hql,int currPage,int pageSize) throws ModelException {
		try {
			Pager pager = new Pager();
			pager.setStartRow(pageSize);
			pager.setPageSize(pageSize);
			return pageFind(hql, null,pager);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	
	public List find(String hql,Object[] values,int currPage,int pageSize) throws ModelException {
		try {
			Pager pager = new Pager();
			pager.setStartRow(pageSize);
			pager.setPageSize(pageSize);
			return pageFind(hql, values,pager);
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 执行指定的修改语句。该方法中的hql语句必须为delete或者update
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:36:38
	 * @param hql 执行语句
	 * @param values hql参数
	 * @return
	 * @throws ModelException
	 */
	public int update(String hql, Object[] values) throws ModelException {
		try {
			Session session = this.getSession();
			Query query = session.createQuery(hql);
			/*if (values != null) {
				for (int i = 0; i < values.length; i++) {
					query.setParameter(i, values[i]);
				}
			}*/
			setParamList(query, values);
			return query.executeUpdate();
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	
	/**
	 * 修改并清空session
	 * @param hql 执行语句
	 * @param values hql参数
	 * @return
	 * @throws ModelException
	 */
	public int updateAndClearSession(String hql, Object[] values) throws ModelException {
		try {
			Session session = this.getSession();
			Query query = session.createQuery(hql);
			setParamList(query, values);
			int result = query.executeUpdate();
			session.clear();
			return result;
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + hql + " false", e);
		}
	}
	
	public int executeSql(String sql,Object[] values)throws ModelException{
		try {
			Session session = this.getSession();
			SQLQuery query = session.createSQLQuery(sql);
			setParamList(query, values);
			return query.executeUpdate();
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + sql + " false", e);
		}
	}
	
	public List executeQuerySql(String sql,Object[] values,Class entityClass)throws ModelException{
		try {
			Session session = this.getSession();
			SQLQuery query = session.createSQLQuery(sql);
			if(entityClass!=null){
				query.addEntity(entityClass);
			}
			setParamList(query, values);
			return query.list();
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ModelException("--------------- execute " + sql + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 修改指定对象的属性值
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:37:27
	 * @param property 属性集合
	 * @param values 参数集合
	 * @param id 主键
	 * @param objectClass 目标Class对象
	 * @param idName id名称
	 */
	/*private void update(String[] property,Object[] values,Serializable id,Class objectClass,String idName){
		
	}*/

	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 返回指定查询语句的记录数量
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:38:12
	 * @param hql HQL语句
	 * @param values 参数集合
	 * @return
	 * @throws ModelException
	 */
	public Integer getCount(String hql, Object[] values) throws ModelException {
		try {
			//获取count Hql语句
			int begin = hql.indexOf("from");
			int end = hql.indexOf(" order ");
			StringBuilder hqlCount = new StringBuilder("select count(*) ");
			if(end==-1){
				hqlCount.append(hql.substring(begin));
			}else{
				hqlCount.append(hql.substring(begin,end));
			}
			String hqlCountStr = hqlCount.toString().replace("fetch", " ");
			////System.out.println("hqlCount = "+ hqlCountStr);
			Long beginTime = System.currentTimeMillis();
			
			List list =find(hqlCountStr, values);
			Long endTime = System.currentTimeMillis();
			//System.out.println("count执行时间="+(endTime-beginTime));
			int countNumber=0;
			if(!list.isEmpty()) {
				if(hql.indexOf("group by") != -1) {
					countNumber=list.size();
				} else {
					countNumber = ((Number) list.get(0)).intValue();
				}
			}
			return countNumber;
//			return ((Number) find(hqlCountStr, values).get(0)).intValue();
		} catch (Exception e) {
			throw new ModelException("--------------- get count " + hql + " false", e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 按条件获取指定对象的纪录总数
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:38:34
	 * @param entity 实体类对象
	 * @param shs 查询帮助集合
	 * @return
	 * @throws ModelException
	 */
	public Integer getCount(Object entity,List<SearchHelper> shs)throws ModelException{
		List<Object> valueList = new ArrayList<Object>();
		OrderHelper helper = null;
		String hql = getQueryHql(entity, shs, helper, valueList );
		return getCount(hql, valueList.toArray());
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 按照指定的条件查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:38:53
	 * @param obj 查询对象
	 * @param sh 查询条件
	 * @return 第一个查询对象
	 * @throws ModelException
	 */
	public T findObject(T obj,SearchHelper sh)throws ModelException{
		List<SearchHelper> shs = new ArrayList<SearchHelper>();
		shs.add(sh);
		return findObject(obj, shs);
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 按照指定的条件查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:39:19
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @return 第一个查询对象
	 * @throws ModelException
	 */
	public T findObject(T obj,List<SearchHelper> shs)throws ModelException{
		OrderHelper helper = null;
		Pager pager = new Pager();
		pager.setPageSize(1);
		List list = find(obj,shs,helper,pager);
		if(list!=null&&list.size()>0){
			return (T)list.get(0);
		}
		return null;
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 跟据指定的条件分页查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:39:41
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @param orderHelper 排序帮助对象
	 * @param pager 分页对象
	 * @return
	 * @throws ModelException
	 */
	@SuppressWarnings("rawtypes")
	public List<T> find(T obj,List<SearchHelper> shs,OrderHelper orderHelper,Pager pager)throws ModelException{
		try{
			List<Object> valueList = new ArrayList<Object>();	
			String hql = getQueryHql(obj, shs, orderHelper,valueList);
			return this.pageFind(hql, valueList.toArray(),pager);
		}catch (Exception e) {
		 
			log.error(e);
			throw new ModelException("按条件查询对象出错",e);
		}
	}	
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 跟据指定的条件分页查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:40:10
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @param orderHelperList 排序帮助对象集合
	 * @param pager 分页对象
	 * @return
	 * @throws ModelException
	 */
	public List<T> find(T obj,List<SearchHelper> shs,List<OrderHelper> orderHelperList,Pager pager)throws ModelException{
		try{
			List<Object> valueList = new ArrayList<Object>();	
			String hql = getQueryHql(obj, shs, orderHelperList,valueList);
			//List list = this.pageFind(hql, valueList.toArray(),pager);
			return this.pageFind(hql, valueList.toArray(),pager);
		}catch (Exception e) {
			throw new ModelException("按条件查询对象出错",e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 跟据指定的条件查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:40:48
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @param orderHelper 排序帮助对象
	 * @return
	 * @throws ModelException
	 */
	public List<T> find(T obj,List<SearchHelper> shs,OrderHelper orderHelper)throws ModelException{
		return find(obj, shs, orderHelper,null);
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 跟据指定的条件查询符合条件的记录
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:41:35
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @return
	 * @throws ModelException
	 */
	public List<T> find(T obj,List<SearchHelper> shs)throws ModelException{
		return find(obj, shs, null);
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 获取HQL语句
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:42:32
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @param orderHelperList 排序帮助对象集合
	 * @param valueList 参数值集合
	 * @return
	 */
	private String getQueryHql(Object obj,List<SearchHelper> shs,List<OrderHelper> orderHelperList,List<Object> valueList){
		if(obj==null){
			throw new ModelException("obj为空");
		}
		Class cl = obj.getClass();
		StringBuilder sb = new StringBuilder("from "+cl.getName()+" o ");
		boolean isfirst = true;
		try{
			//设置查询语句
			if(shs!=null){
				for (SearchHelper sh : shs) {
					Type type = sh.getType();
					String property = sh.getAttr();//获取属性
					//获取条件查询连接类型
					LinkType linkType = sh.getLinkType();
					String linkStr = " and ";
					if(linkType.equals(LinkType.OR)){
						linkStr = " or ";
					}
					//fetch，left fetch连接处理
					if(Type.FETCH==type||Type.LEFTFETCH==type){
						if(Type.FETCH==type){
							sb.append(" join fetch ").append(property);
						}else{
							sb.append(" left join fetch ").append(property);
						}
						continue;
					}else if(isfirst){
						sb.append(" where 1=1 ");
						isfirst = false;
					}
							
					String propertyValueName = sh.getAttrValueName();
					Object propertyValue = getPropertyValue(obj, propertyValueName);//获取属性值
					
					//如果属性值为空且查询的条件不为该属性值不为is not null 则 跳出
					////System.out.println(propertyValue+"..");
					if(propertyValue==null&Type.NOTNULL!=type&Type.BETWEEN!=type&Type.IN!=type&Type.ISNULL!=type&Type.NOTIN!=type){
						continue;
					}
					if(Type.BETWEEN!=type&&Type.IN!=type&Type.NOTIN!=type){
						sb.append(linkStr).append(property);
					}
					if(Type.EQ == type){
						sb.append(" =?");
					}else if(Type.GT == type){
						sb.append(" > ?");
					}else if(Type.LT == type){
						sb.append(" < ?");
					}else if(Type.GE == type){
						sb.append(" >= ?");
					}else if(Type.LIKE == type){
						sb.append(" like ?");
						propertyValue = "%"+propertyValue+"%";
					}else if(Type.BEGINLIKE == type){
						sb.append(" like ?");
						propertyValue = "%"+propertyValue;
					}else if(Type.ENDLIKE == type){
						sb.append(" like ?");
						propertyValue = propertyValue+"%";
					}else if(Type.LE == type){
						sb.append(" <=?");
					}else if(Type.NOTEQ == type){
						sb.append(" !=?");
					}else if(Type.ISNULL == type){
						sb.append(" is null ");
						propertyValue = null;
					}
					else if(Type.NOTNULL == type){
						sb.append(" is not null");
						propertyValue = null;
					}else if(Type.BETWEEN == type){
						propertyValue = null;
						String minProperty = propertyValueName+"Min";
						String maxProperty=propertyValueName+"Max";
						Object minpropertyValue = getPropertyValue(obj, minProperty);
						Object maxpropertyValue = getPropertyValue(obj, maxProperty);
						if (minpropertyValue != null & maxpropertyValue != null) {
							//如果过滤的是日期类型，结束日期的时间增加至23:59:59
							if(maxpropertyValue instanceof Date) {
								maxpropertyValue = DateHelper.dateAddOneDay((Date) maxpropertyValue);
							}
							sb.append(linkStr).append(property);
							sb.append(" between ? and ?");
							valueList.add(minpropertyValue);
							valueList.add(maxpropertyValue);
						}else if(minpropertyValue!=null){
							sb.append(linkStr).append(property);
							sb.append(" >=?");
							valueList.add(minpropertyValue);
						}else if(maxpropertyValue!=null){
							sb.append(linkStr).append(property);
							sb.append(" <=?");
							valueList.add(maxpropertyValue);
						}
					}else if(Type.IN == type){
						propertyValue = null;
						String inProperty = propertyValueName+"List";
						List inpropertyValue = (List)getPropertyValue(obj, inProperty);
						if(inpropertyValue!=null&&inpropertyValue.size()>0){
							//处理oracle中in不能超过1000的情况
							sb.append(linkStr).append("(");
							int size = inpropertyValue.size();
							int incount = size/1000;
							int count = size%1000;
							if(incount>0){
								for(int i=1;i<=incount;i++){
									if(i!=1){
										sb.append(" or ");
									}
									sb.append(property).append(" in (");
									for(int j=0;j<1000;j++){
										if(j!=999){
											sb.append(" ?,");
										}else{
											sb.append(" ? ");
										}
									}
									sb.append(")");
								}
								if(count!=0){
									sb.append(" or ").append(property).append(" in (");
									for(int i=1;i<=count;i++){
										if(i!=count){
											sb.append(" ?,");
										}else{
											sb.append(" ? ");
										}
									}
									sb.append(")");
								}
							}else{
								sb.append(property).append(" in (");
								for(int i=1;i<=count;i++){
									if(i!=count){
										sb.append(" ?,");
									}else{
										sb.append(" ? ");
									}
								}
								sb.append(")");
							}
							sb.append(")");
							/*sb.append(linkStr);
							sb.append(" (");
							int size = inpropertyValue.size()-1;
							for(int i=0;i<=size;i++){
								if(i!=size){
									sb.append(property).append(" = ? or ");
								}else{
									sb.append(property).append(" = ? ");
								}
							}
							sb.append(")");*/
							valueList.add(inpropertyValue);
						}
					}else if(Type.NOTIN == type){
						propertyValue = null;
						String inProperty = propertyValueName+"List";
						List inpropertyValue = (List)getPropertyValue(obj, inProperty);
						if(inpropertyValue!=null&&inpropertyValue.size()>0){
							sb.append(linkStr).append(property);
							sb.append(" not in (");
							int size = inpropertyValue.size()-1;
							for(int i=0;i<=size;i++){
								if(i!=size){
									sb.append(" ?,");
								}else{
									sb.append(" ? ");
								}
							}
							sb.append(")");
							valueList.add(inpropertyValue);
						}
					}
					if(propertyValue!=null){
						valueList.add(propertyValue);
					}
				}
			}
			if(orderHelperList!=null&&orderHelperList.size()!=0){
				sb.append(" order by ");
				for (OrderHelper orderHelper : orderHelperList) {
					if(OrderHelper.Type.ASC == orderHelper.getType()) {
						sb.append(orderHelper.getPropertyName()).append(" asc ,");
					} else {
						sb.append(orderHelper.getPropertyName()).append(" desc ,");
					}
				}
				if(sb.lastIndexOf(",")!=-1){
					return sb.substring(0, sb.lastIndexOf(","));
				}
			}
			
			return sb.toString();
		}catch (Exception e) {
			throw new ModelException("封装查询语句出错",e);
		}
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 获取执行的hql语句
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:43:23
	 * @param obj 查询对象
	 * @param shs 查询条件
	 * @param orderHelper 排序帮助对象
	 * @param valueList 参数值集合
	 * @return
	 */
	private String getQueryHql(Object obj,List<SearchHelper> shs,OrderHelper orderHelper,List<Object> valueList){
		List<OrderHelper> orderHelperList = new ArrayList<OrderHelper>();
		if(orderHelper!=null){
			orderHelperList.add(orderHelper);
		}
		return getQueryHql(obj, shs, orderHelperList, valueList);
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 获取指定对象的指定属性值
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:44:45
	 * @param obj 指定的javaBean对象
	 * @param property 指定的属性。请保证在指定对象下存在get...（）方法
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Object getPropertyValue(Object obj,String property){
		String[] propertyChain = property.split("\\.");//获取属性链
		////System.out.println("propertyChain:"+propertyChain.length);
		Object result = null;
		for (String pro : propertyChain) {
			////System.out.println("属性："+pro);
			if(obj==null){
				break;
			}
			String methodName = "get"+pro.substring(0,1).toUpperCase()+pro.substring(1);
			Class cl = obj.getClass();
			try {
				Method method = cl.getMethod(methodName, null);
				result = method.invoke(obj, null);
				////System.out.println(methodName+":"+result);
				if(result!=null){
					String resultStr = result.toString().trim();
					if(!resultStr.equals("")){
						obj = result;
						continue;
					}
				}
				result = null;
				obj = null;
			} catch (Exception e) {
				//e.printStackTrace();
				throw new ModelException("不存在该方法 "+methodName);
			}
		}
		return result;
	}
	
	/**
	 * 
	 * @ClassName: BaseDaoTemplet.java
	 * @Description: 修改排序
	 * @Author:zhucong
	 * @CreateDate:2013-6-7 下午5:45:07
	 * @param ids 主键集合
	 * @param nums 展现次序
	 */
	public void updateGradation(Serializable[] ids,int[] nums){
		String hql = "update "+ entityClass.getName()+" o set o.gradation =? where o.id=?";
		for(int i =0;i<ids.length;i++){
			update(hql, new Object[]{nums[i],ids[i]});
		}
	}
	
	/**
	 * 批量更新删除标识
	 * @param ids id集合
	 * @param status 目标状态
	 */
	public void opDelFlag(Serializable[] ids, Integer status) {
		if(ids != null && ids.length > 0 && status != null) {
			for (Serializable id : ids) {
				String hql = "update " + entityClass.getName() + " o set o.delFlag = ? where o.id = ? and o.delFlag = ?";
				Integer oldStatus = null;
				if(SysStatic.NORMALDELFLAG.equals(status)) {
					oldStatus = SysStatic.DELFLAG;
				} else {
					oldStatus = SysStatic.NORMALDELFLAG;
				}
				update(hql, new Object[]{status, id, oldStatus});
			}
		}
	}
	
	/**
	 * 根据字段的返回值类型，获取目标值
	 * @param srcVal 字段的源字符串值
	 * @param retClazz 字段的返回值类型
	 * @return
	 */
	private Map<String, Object> getTargetVal(Object srcVal, Class<?> retClazz) {
		boolean isTargetUpdate = false; //是否允许目标字段更新
		Object targetVal = null; //目标值
		//如果字段的字符串不为空，标识为可更新
		if(srcVal != null) {
			isTargetUpdate = true;
			String srcValStr = String.valueOf(srcVal).trim();
			//如果目标字段的字符串不为空串，将字符串转换为目标值
			if(!"".equals(srcValStr)) {
				if(Integer.class.equals(retClazz)) {
					targetVal = Integer.parseInt(srcValStr);
				} else if(Float.class.equals(retClazz)) {
					targetVal = Float.parseFloat(srcValStr);
				} else if(Double.class.equals(retClazz)) {
					targetVal = Double.parseDouble(srcValStr);
				} else if(Long.class.equals(retClazz)) {
					targetVal = Long.parseLong(srcValStr);
				} else {
					targetVal = srcVal;
				}
			}
			
		}
		Map<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put("targetVal", targetVal);
		resultMap.put("isTargetUpdate", isTargetUpdate);
		return resultMap;
	}
	
	/**
	 * 根据对象的非空属性生成HQL语句进行更新
	 * @param entity 实体对象
	 * @return
	 * @throws Exception
	 */
	public int updateByConvertHql(T entity){
		int updateCount = 0;
		try {
		if(entity != null) {
			List<Object> valueList = new ArrayList<Object>();
			Class<? extends Model> clazz = entity.getClass();
			//获取对象的id值
			Method getIdMethod = clazz.getMethod("getId");
			String id = String.valueOf(getIdMethod.invoke(entity));
			//清空id值（因不需要更新id）
			Method setIdMethod = clazz.getMethod("setId", String.class);
			setIdMethod.invoke(entity, new Object[]{null});
			
			Method[] methods = clazz.getDeclaredMethods();
			if(methods != null && methods.length > 0) {
				StringBuilder paramSb = new StringBuilder();
				for (int i = 0, j = 0; i< methods.length; i++) {
					Method method = methods[i];
					String methodName = method.getName();
					//获取不带Transient注解的get方法，拼接update语句
					if(methodName.startsWith("get") && !methodName.endsWith("Desc") && !methodName.endsWith("Tips") 
								&& !method.isAnnotationPresent(Transient.class)) {
						Object result = method.invoke(entity);
						boolean isTargetUpdate = false; //是否允许数字字段更新
						//如果get方法以Str结尾（即数字字段字符串），进行数字字段的更新判断处理
						if(methodName.endsWith("Str")) {
							methodName = methodName.substring(0, methodName.length() - 3);
							Class<?> retClazz = clazz.getMethod(methodName).getReturnType(); //数字字段的返回值类型
							Map<String, Object> resultMap = getTargetVal(result, retClazz); //根据字段的返回值类型，获取目标值
							isTargetUpdate = (boolean) resultMap.get("isTargetUpdate"); //设置是否允许目标字段更新
							result = resultMap.get("targetVal"); //设置目标值
						}
						//如果目标字段可更新，进行更新；非指定的目标字段，如果值不为空才进行更新
						if(isTargetUpdate || result != null) {
							String fieldName = methodName.substring(3, 4).toLowerCase() + methodName.substring(4); //属性名
							if(j++ > 0) {
								paramSb.append(",");
							}
							//如果属性为BaseModel的对象类型，获取对象的id值进行更新
							if(result instanceof BaseModel) {
								BaseModel baseModel = (BaseModel) result;
								paramSb.append("o.").append(fieldName).append(".id = ?");
								valueList.add(baseModel.getId());
							} else {
							//如果属性为普通类型，直接更新
								paramSb.append("o.").append(fieldName).append(" = ?");
								valueList.add(result);
							}
						}
					}
				}
				if(paramSb.length() > 0) {
					StringBuilder sb = new StringBuilder();
					sb.append("update ").append(clazz.getSimpleName()).append(" o set ").append(paramSb).append(" where o.id = ?");
					valueList.add(id);
					updateCount = update(sb.toString(), valueList.toArray());
				}
			}
		}
		} catch (Exception e) {
			e.getMessage();
		}
		return updateCount;
	}
}
